using System;
using System.Text;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using ManagedAPI;

namespace UnitTest
{
	/// <summary>
	/// Summary description for DataBaseTest
	/// </summary>
	[TestClass]
	public class DatabaseTest
	{
		public DatabaseTest()
		{

		}

		#region Additional test attributes
		//
		// You can use the following additional attributes as you write your tests:
		//
		// Use ClassInitialize to run code before running the first test in the class
		// [ClassInitialize()]
		// public static void MyClassInitialize(TestContext testContext) { }
		//
		// Use ClassCleanup to run code after all tests in a class have run
		// [ClassCleanup()]
		// public static void MyClassCleanup() { }
		//
		// Use TestInitialize to run code before running each test 
		private bool open_result;
		[TestInitialize()]
		public void MyTestInitialize()
		{
			open_result = Database.Open(UnderstandGlobalData.GetFileName());
			Assert.IsTrue(open_result);
		}
		//
		// Use TestCleanup to run code after each test has run
		[TestCleanup()]
		public void MyTestCleanup()
		{
			Database.Close();
			open_result = false;
		}
		//
		#endregion

		/// <summary>
		/// Tests the open close.
		/// </summary>
		[TestMethod]
		public void DatabaseTest_OpenClose()
		{
			if (open_result)
			{
				String file_name = System.IO.Path.GetFileName(Database.FileName());
				Assert.AreEqual("testsdk.udb", file_name);

				// Try opening it again, while the first is already open
				bool second_open_result = Database.Open(UnderstandGlobalData.GetFileName());
				Assert.IsFalse(second_open_result);

				UdbLanguage lang = Database.Language();
				Assert.AreEqual(UdbLanguage.Udb_language_C, lang);

				String langstr = Database.LanguageString();
				Assert.AreEqual("C", langstr);
			}
		}

		/// <summary>
		/// Tests the get all entities.
		/// </summary>
		[TestMethod]
		public void DatabaseTest_GetAllEntities()
		{
			if (open_result)
			{
				Entity[] entList = Database.GetAllEntities();
				Assert.AreEqual(196, entList.Length);
			}
		}

		[TestMethod]
		public void DatabaseTest_GetFileEntities()
		{
			if (open_result)
			{
				const int NUM_FILES = 10;
				Entity[] entList = Database.GetFileEntities();
				Assert.AreEqual(NUM_FILES, entList.Length);

				FileEntity[] files = Database.GetFileEntityArray();
				Assert.AreEqual(NUM_FILES, files.Length);
			}
		}

		[TestMethod]
		public void DatabaseTest_GetAllFunctions()
		{
			if (open_result)
			{
				MethodType[] allFunctions = Database.GetAllFunctions();
				Assert.AreEqual(8, allFunctions.Length);
			}
		}

		[TestMethod]
		public void DatabaseTest_GetAllStructs()
		{
			if (open_result)
			{
				ClassType[] structs = Database.GetAllStructTypes();
				Assert.AreEqual(1, structs.Length);
			}
		}

		[TestMethod]
		public void DatabaseTest_LookupFile()
		{
			if (open_result)
			{
				Entity nullEnt = Database.LookupFile(null);
				Assert.IsNull(nullEnt);

				Entity ent = Database.LookupFile("classes.h");
				Assert.IsTrue(ent != null);

				Database.Close();

				open_result = Database.Open(UnderstandGlobalData.GetFileName());
				Assert.IsTrue(open_result);
				Entity fileEntA = Database.LookupFile("classes.h");
				// twice in a row
				Entity fileEntB = Database.LookupFile("classes.h");
				Assert.IsTrue(Object.ReferenceEquals(fileEntA, fileEntB), "The objects should be the same");

				FileEntity nullFile = Database.LookupFileEntity(null);
				Assert.IsNull(nullFile);
				nullFile = Database.LookupFileEntity("classes.h");
				Assert.AreEqual("classes.h", nullFile.NameShort);
			}
		}

		[TestMethod]
		public void DatabaseTest_LookupEntityUnique()
		{
			if (open_result)
			{
				Entity[] ents = Database.GetAllEntities();
				Entity entFifth = ents[5];
				String unique_name = entFifth.NameUnique;

				Entity fooNULL = Database.LookupEntityByUniqueName("");
				Assert.IsNull(fooNULL);
				fooNULL = Database.LookupEntityByUniqueName(null);
				Assert.IsNull(fooNULL);

				Entity copy = Database.LookupEntityByUniqueName(unique_name);
				Assert.IsTrue(Object.ReferenceEquals(entFifth, copy), "Look up Entity by Unique Name isn't so hot after all");
			}
		}

		[TestMethod]
		public void DatabaseTest_Misc()
		{
			ClassType[] classes = Database.GetAllClassTypes();
			Assert.AreEqual(13, classes.Length);

			Entity[] enums = Database.GetAllEnums();
			Assert.AreEqual(2, enums.Length);

			Entity[] typedefs = Database.GetAllTypeDefs();
			Assert.AreEqual(3, typedefs.Length);
		}
		[TestMethod]
		public void DatabaseTest_LookupEntity()
		{
			if (open_result)
			{
				MethodType functionEnt = Database.LookupEntity(typeof(MethodType), "BigAndWideMethod", "Function") as MethodType;
				Assert.IsNotNull(functionEnt);
				Assert.AreEqual("BigAndWideMethod", functionEnt.NameSimple);

				functionEnt = Database.LookupEntity(typeof(MethodType), "foo::Util::BigAndWideMethod", "Function") as MethodType;
				Assert.IsNotNull(functionEnt);
				Assert.AreEqual("foo::Util::BigAndWideMethod", functionEnt.NameLong);
			}
		}
		[TestMethod]
		public void DatabaseTest_LookupEntitybyReference()
		{
			if (open_result)
			{
				int line = 26;
				int column = 16;
				MethodType functionEnt = (MethodType)Database.LookupEntitybyReference(typeof(MethodType), "foo_Util.h", "BigAndWideMethod", line, column);
				Assert.IsNotNull(functionEnt);
				Assert.AreEqual("BigAndWideMethod", functionEnt.NameSimple);
			}
		}
	}
}
